package org.csu.onlineedubackend.aop;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.csu.onlineedubackend.annotation.ApiLog;
import org.csu.onlineedubackend.entity.Log;
import org.csu.onlineedubackend.mapper.LogMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.aspectj.lang.annotation.AfterThrowing;

import jakarta.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Aspect
@Component
public class ApiLogAspect {

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private LogMapper logMapper;

    @Pointcut("@annotation(org.csu.onlineedubackend.annotation.ApiLog) || @within(org.springframework.web.bind.annotation.RestController)")
    public void apiLogPointcut() {}

    @Before("apiLogPointcut()")
    public void logApiCall(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        String uri = request.getRequestURI();
        String httpMethod = request.getMethod();
        String ip = request.getRemoteAddr();
        String userAgent = request.getHeader("User-Agent");
        String params = request.getQueryString();

        String description = "";
        ApiLog apiLog = method.getAnnotation(ApiLog.class);
        if (apiLog != null) {
            description = apiLog.value();
        }

        Log log = new Log();
        log.setLogType("API");
        log.setLevel("INFO");
        log.setModule("接口访问");
        log.setAction(httpMethod);
        log.setTargetId(uri);
        log.setTargetType("API");
        log.setMessage("接口访问: " + uri + (description.isEmpty() ? "" : ("，描述：" + description)) + (params != null ? "，参数：" + params : ""));
        log.setIpAddress(ip);
        log.setUserAgent(userAgent);
        log.setCreatedAt(LocalDateTime.now());
        logMapper.insert(log);
    }

    @AfterThrowing(pointcut = "apiLogPointcut()", throwing = "ex")
    public void logApiException(JoinPoint joinPoint, Throwable ex) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        String uri = request.getRequestURI();
        String httpMethod = request.getMethod();
        String ip = request.getRemoteAddr();
        String userAgent = request.getHeader("User-Agent");
        String params = request.getQueryString();

        String description = "";
        ApiLog apiLog = method.getAnnotation(ApiLog.class);
        if (apiLog != null) {
            description = apiLog.value();
        }

        Log errorLog = new Log();
        errorLog.setLogType("API");
        errorLog.setLevel("ERROR");
        errorLog.setModule("接口访问");
        errorLog.setAction(httpMethod);
        errorLog.setTargetId(uri);
        errorLog.setTargetType("API");
        errorLog.setMessage("接口异常: " + uri
            + (description.isEmpty() ? "" : ("，描述：" + description))
            + (params != null ? "，参数：" + params : "")
            + "，异常信息：" + ex.getClass().getSimpleName() + ": " + ex.getMessage());
        errorLog.setIpAddress(ip);
        errorLog.setUserAgent(userAgent);
        errorLog.setCreatedAt(LocalDateTime.now());
        try {
            logMapper.insert(errorLog);
        } catch (Exception ignore) {}
    }
}